﻿using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;

namespace BLL.Utils
{
    internal static class PassEncHelper
    {
        private const int iterationCount = 10;
        private const int keySize = 128/8;
        private const int saltSize = 128/8;
        private const int IVSize = 128/8;

        private static byte[] EncryptDecrypt(byte[] inputBytes, ICryptoTransform transform)
        {
            //memory stream for output
            var memStream = new MemoryStream();

            try
            {
                //setup the cryption - output written to memstream
                using (var cryptStream = new CryptoStream(memStream, transform, CryptoStreamMode.Write))
                {
                    //write data to cryption engine
                    cryptStream.Write(inputBytes, 0, inputBytes.Length);

                    //we are finished
                    cryptStream.FlushFinalBlock();

                    //get result
                    var output = memStream.ToArray();

                    return output;
                }
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static byte[] DecryptData(string pass, byte[] encData)
        {
            var saltBytes = encData.Take(saltSize).ToArray();
            var ivBytes = encData.Skip(saltSize).Take(IVSize).ToArray();
            var inputBytes = encData.Skip(saltSize + IVSize).ToArray();

            var deriveBytes = new Rfc2898DeriveBytes(pass, saltBytes, iterationCount);
            var keyBytes = deriveBytes.GetBytes(keySize);

            return EncryptDecrypt(inputBytes, new AesManaged().CreateDecryptor(keyBytes, ivBytes));
        }

        public static byte[] EncryptData(string pass, byte[] decData)
        {
            var deriveBytes = new Rfc2898DeriveBytes(pass, saltSize, iterationCount);
            var keyBytes = deriveBytes.GetBytes(keySize);
            var r = new Random();
            var ivBytes = new byte[IVSize];
            r.NextBytes(ivBytes);

            var encData = EncryptDecrypt(decData, new AesManaged().CreateEncryptor(keyBytes, ivBytes));
            if (encData == null)
                return null;

            return new[] { deriveBytes.Salt, ivBytes, encData }.SelectMany(x => x).ToArray();
        }
    }
}